﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace AAA.Base.Image
{
    //儲存使用4-Connected Components演算法時區塊的資訊
    public class BlockLabel
    {
        //存放區塊編號所對應的點
        Dictionary<int, List<Point>> _dicLabel;
        //存放點座標對應的區塊編號
        Dictionary<Point, int> _dicPointLabel;
        //存放區塊左上角的座標
        Dictionary<int, Point> _dicLeftTop;
        //存放區塊右下角的座標
        Dictionary<int, Point> _dicRightBottom;
        //存放最大區塊的中心點座標
        private Point _pMaxCenter;
        //最大區塊的編號
        private int _iMaxLabel = -1;
        //最大區塊的點數
        private int _iMaxCount = 0;      

        public BlockLabel()
        {
            _dicLabel = new Dictionary<int, List<Point>>();
            _dicPointLabel = new Dictionary<Point, int>();
            _dicLeftTop = new Dictionary<int, Point>();
            _dicRightBottom = new Dictionary<int, Point>();
        }

        public int MaxLabel
        {
            get { return _iMaxLabel; }
            set { _iMaxLabel = value; }
        }

        public int MaxCount
        {
            get { return _iMaxCount; }
            set { _iMaxCount = value; }
        }

        public Point MaxCenter
        {
            get { return _pMaxCenter; }
            set { _pMaxCenter = value; }
        }

        public void AddPoint(int iLabel, Point point)
        {
            List<Point> lstPoint;

            if (_dicLabel.ContainsKey(iLabel))
            {                
                _dicLabel[iLabel].Add(point);                                

                if (point.X < _dicLeftTop[iLabel].X)
                    _dicLeftTop[iLabel] = new Point(point.X, _dicLeftTop[iLabel].Y);

                if (point.Y < _dicLeftTop[iLabel].Y)
                    _dicLeftTop[iLabel] = new Point(_dicLeftTop[iLabel].X, point.Y);

                if (point.X > _dicRightBottom[iLabel].X)
                    _dicRightBottom[iLabel] = new Point(point.X, _dicRightBottom[iLabel].Y);

                if (point.Y > _dicRightBottom[iLabel].Y)
                    _dicRightBottom[iLabel] = new Point(_dicRightBottom[iLabel].X, point.Y);
            }
            else
            {
                lstPoint = new List<Point>();
                lstPoint.Add(point);
                _dicLabel.Add(iLabel, lstPoint);
                _dicLeftTop.Add(iLabel, new Point(point.X, point.Y));
                _dicRightBottom.Add(iLabel, new Point(point.X, point.Y));
            }

            _dicPointLabel.Add(point, iLabel);
        }

        public Point GetLeftTop(int iLabel)
        {
            if (_dicLeftTop.ContainsKey(iLabel))
                return _dicLeftTop[iLabel];

            return new Point(-1, -1);
        }

        public Point GetRightBottom(int iLabel)
        {
            if (_dicRightBottom.ContainsKey(iLabel))
                return _dicRightBottom[iLabel];

            return new Point(-1, -1);
        }

        public int GetPointLabel(Point point)
        {
            if (_dicPointLabel.ContainsKey(point) == false)
                return -1;
            return _dicPointLabel[point];
        }

        public List<Point> GetMaxBlock()
        {
            _iMaxLabel = -1;
            _iMaxCount = 0;

            foreach (int iLabel in _dicLabel.Keys)
            {
                if (_dicLabel[iLabel].Count > _iMaxCount)
                {
                    _iMaxCount = _dicLabel[iLabel].Count;
                    _iMaxLabel = iLabel;
                }
            }

            return _dicLabel[_iMaxLabel];
        }

        public void MergeLabel(int iSourceLabel, int iDestinationLabel)
        {
            if ((_dicLabel.ContainsKey(iSourceLabel) == false) ||
                (_dicLabel.ContainsKey(iDestinationLabel) == false))
                return;

            List<Point> lstPoint = _dicLabel[iSourceLabel];

            foreach (Point point in lstPoint)
            {
                _dicLabel[iDestinationLabel].Add(point);
                _dicPointLabel[point] = iDestinationLabel;

                if (point.X < _dicLeftTop[iDestinationLabel].X)
                    _dicLeftTop[iDestinationLabel] = new Point(point.X, _dicLeftTop[iDestinationLabel].Y);

                if (point.Y < _dicLeftTop[iDestinationLabel].Y)
                    _dicLeftTop[iDestinationLabel] = new Point(_dicLeftTop[iDestinationLabel].X, point.Y);

                if (point.X > _dicRightBottom[iDestinationLabel].X)
                    _dicRightBottom[iDestinationLabel] = new Point(point.X, _dicRightBottom[iDestinationLabel].Y);

                if (point.Y > _dicRightBottom[iDestinationLabel].Y)
                    _dicRightBottom[iDestinationLabel] = new Point(_dicRightBottom[iDestinationLabel].X, point.Y);


            }

            _dicLabel.Remove(iSourceLabel);
        }
    }

    //儲存Y, Cb, Cr的資訊
    public class YCbCr
    {
        private double _dY;
        private double _dCb;
        private double _dCr;

        public YCbCr()
        {
        }

        public YCbCr(double dY, double dCb, double dCr)
        {
            _dY = Math.Max(0.0, Math.Min(1.0, dY));
            _dCb = Math.Max(-0.5, Math.Min(0.5, dCb));
            _dCr = Math.Max(-0.5, Math.Min(0.5, dCr));
        }


        public double Y
        {
            get { return _dY; }
            set { _dY = value; }
        }

        public double Cb
        {
            get { return _dCb; }
            set { _dCb = value; }
        }

        public double Cr
        {
            get { return _dCr; }
            set { _dCr = value; }
        }
    }

}
